import base64
import pickle

from django.shortcuts import render

# Create your views here.
from django_redis import get_redis_connection
from rest_framework.response import Response
from rest_framework.views import APIView

from goods.models import SKU

'''
import pickle
import base64
cart ={
    '1':{'count':5,'selected':True}
}
dumps = pickle.dumps(cart)       #python ->bytes
encode = base64.b64encode(dumps) # bytes -> 转换格式的二进制
encode.decode()     # 转换格式的二进制 ->字符串

decode = base64.b64decode(encode)  # 转换格式的二进制 -> bytes
pickle.loads(decode)    # bytes -> python
'''
from .serializers import CartSerializer, CartSKUSerializer, CartSKUIDSerialzier

from rest_framework import status
class CartAPIView(APIView):

    def perform_authentication(self, request):
        pass
    # 添加购物车
    def post(self,request):
        # 1.后端接收数据（sku_id,count,selected）
        data = request.data
        # 2.验证数据（验证商品id是否有对应的商品，商品的个数）
        serializer = CartSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        # 3.获取数据
        sku_id = serializer.validated_data.get('sku_id')
        count = serializer.validated_data.get('count')
        selected = serializer.validated_data.get('selected')
        # 4.得到用户的信息
        try:
            user = request.user
        except Exception as e:
            user = None
        # 5.根据用户的信息进行判断
        # is_authenticated 认证用户
        # request.user.is_authenticated
        if user is not None and user.is_authenticated:
            # user 不能为 none 而且必须是认证用户
            # 6.登陆用户保存在redis中
            #     6.1  连接redis
            redis_conn = get_redis_connection('cart')
            #     6.2  保存数据
            # hash
            # redis_conn.hset('cart_%s'%user.id,sku_id,count)
            # # set
            # if selected:
            #     redis_conn.sadd('cart_selected_%s'%user.id,sku_id)
            #A 创建管道
            pl = redis_conn.pipeline()
            #B 将redis指令添加到 管道中
            pl.hincrby('cart_%s'%user.id,sku_id,count)

            # set
            if selected:
                pl.sadd('cart_selected_%s'%user.id,sku_id)

            #C,执行管道
            pl.execute()
            #     6.3  返回相应
            return Response(serializer.data)

        else:
            # 7.未登录用户保存在cookie中
            #     7.1  先读取cookie信息
            cookie_str = request.COOKIES.get('cart')
            #     7.2  判断是否有 购物车信息
            if cookie_str is not None:
                #         如果有则是加密的数据
                #7.2.1 将加密之后的数据进行base64解码
                decode = base64.b64decode(cookie_str)

                # 7.2.2 需要将二进制转换为字典
                # cookie_cart = {sku_id:{c/home/python/Desktop/meiduo_38 (复件)ount:xxx,selected:xxx}}
                cookie_cart = pickle.loads(decode)
            else:
                #         如果没有,则定义一个空字典
                cookie_cart = {}

            #     7.3 判断这个商品是否在cookie中
            # cookie_cart = {sku_id:{count:xxx,selected:xxx}}
            if sku_id in cookie_cart:

                #         如果在则累加数据
                # 先获取之前的数据
                original_count = cookie_cart[sku_id]['count']
                #累加
                count += original_count

            # 如果不在则 直接添加
            cookie_cart[sku_id]={
                'count':count,
                'selected':selected
            }
            #     cookie_cart = {1:{'count':5,'selected':True}}
            #     7.4 将购物车数据进行加密处理
            # 7.4.1 将字典转换为 bytes类型
            dumps = pickle.dumps(cookie_cart)
            #7.4.2 对bytes类型进行编码
            encode = base64.b64encode(dumps)


            #     7.5 返回相应
            response = Response(serializer.data)
            print(serializer.data)
            response.set_cookie('cart',encode.decode())  # key + 字符串

            return response

    def get(self,request):
        # 1.获取用户信息
        try:
            user = request.user
        except Exception as e:
            user = None
        # 2.根据用户信息进行判断
        # request.user.is_authenticated
        if user is not None and user.is_authenticated:
            # 3.登陆用户从redis中获取数据
            #     3.1 连接redis
            redis_conn = get_redis_connection('cart')
            #     3.2 获取hash
            # {sku_id:count}
            sku_id_counts = redis_conn.hgetall('cart_%s'%user.id)
            # ,set 选中的id
            # [sku_id]
            selected_ids = redis_conn.smembers('cart_selected_%s'%user.id)
            #     3.3 都获取商品id，count，selected

            """
            因为redis获取的数据格式 和 cookie获取的数据格式不一致
            所以 根据id去获取商品的详细信息的业务逻辑不能统一

            我们就选择让数据 统一就行了

            为什么选择将 redis数据转换为 cookie格式
            redis但是数据获取之后都是 bytes

            # cookie_cart = {sku_id:{count:xxx,selected:True}}
            """
            cookie_cart = {}
            for sku_id,count in sku_id_counts.items():

                # sku_id 4
                #selected_ids = [1,2,3]
                # selected_ids 保存的是 选中商品的id

                if sku_id in selected_ids:
                    flag = True
                else:
                    flag=False
                # sku_id格式
                cookie_cart[int(sku_id)] = {
                    'count':int(count),
                    'selected': sku_id in selected_ids   #flag
                }
                print(cookie_cart)
        else:
            # 4.未登录用户从cookie中获取数据
            #     4.1 获取cookie数据
            cookie_str = request.COOKIES.get('cart')
            #     4.2 判断cart数据
            if cookie_str is not None:
                #         如果有则进行解密
                # cookie_cart = {sku_id:{count:xxx,selected:True}}
                cookie_cart = pickle.loads(base64.b64decode(cookie_str))
            else:
                #         如果没有就是空
                cookie_cart = {}
            #     4.3.都获取商品id，count，selected


        # cookie_cart = {sku_id:{count:xxx,selected:True},sku_id:{count:xxx,selected:True},}
        # 5.根据id去获取商品的详细信息 sku
        ids = cookie_cart.keys()  # [1,3,4,5,6]
        skus = SKU.objects.filter(pk__in=ids)  # [sku,sku,sku]

        # 对 skus 进行遍历
        for sku in skus:
            sku.count = cookie_cart[sku.id]['count']
            sku.selected=cookie_cart[sku.id]['selected']

        # 6.将对象转换为字典
        serializer = CartSKUSerializer(skus,many=True)

        return Response(serializer.data)


    def put(self,request):
        # 1.接收数据
        data = request.data
        # 2.验证数据
        serializer = CartSerializer(data=data)   #redis 不用传实例对象
        serializer.is_valid(raise_exception=True)
        # 3.获取数据
        sku_id = serializer.validated_data.get('sku_id')
        count = serializer.validated_data.get('count')
        selected = serializer.validated_data.get('selected')
        # 4.获取用户信息
        try:
            user = request.user
        except Exception as e:
            user = None
        # request.user.is_authenticated
        # 5.根据用户的状态进行判断
        if user is not None and user.is_authenticated:

            # 6.登陆用户更新redis
            #     6.1 连接redis
            redis_conn = get_redis_connection('cart')
            #     6.2 更新hash
            redis_conn.hset('cart_%s'%user.id,sku_id,count)
            # set
            if selected:
                redis_conn.sadd('cart_selectecd_%s'%user.id,sku_id)
            else:
                redis_conn.srem('cart_selected_%s'%user.id,sku_id)

            #     6.3 返回数据
            return Response(serializer.data)

        else:
            # 7.未登录用户更新cookie
            #     7.1 先获取cart数据
            cookie_str = request.COOKIES.get('cart')
            #     7.2 判断cart数据
            if cookie_str is not None:
                #         如果有则解密
                cookie_cart = pickle.loads(base64.b64decode(cookie_str))
            else:
                #         如果没有则初始化
                cookie_cart = {}
            # cookie_cart = {sku_id:{'count':xxx,'selected':True}}
            #     7.3 更新数据
            if sku_id in cookie_cart:
                cookie_cart[sku_id]={
                    'count':count,
                    'selected':selected
                }
            #     7.4 对数据进行加密
            cookie_encode = base64.b64encode(pickle.dumps(cookie_cart))
            #     7.5 返回数据
            response = Response(serializer.data)

            response.set_cookie('cart',cookie_encode.decode())

            return response



    # def put(self,request):
    #     data = request.data
    #     serializer = CartSerializer(data=data)
    #     serializer.is_valid(raise_exception=True)
    #     sku_id = serializer.validated_data.get('sku_id')
    #     count = serializer.validated_data.get('count')
    #     selected = serializer.validated_data.get('selected')
    #     try:
    #         user = request.user
    #     except Exception as e:
    #         user = None
    #     if user is not None and user.is_authenticated:
    #         redis_conn = get_redis_connection('cart')
    #         redis_conn.hset('cart_%s')


    def delete(self,request):
        # 1.接收数据
        data = request.data
        # 2.验证数据
        serializer= CartSKUIDSerialzier(data=data)
        serializer.is_valid(raise_exception=True)
        # 3.获取数据
        sku_id=serializer.validated_data['sku_id']
        # 4.获取用户信息
        try:
            user = request.user
        except Exception:
            user = None
        # 5.根据用户信息进行判断
        if user is not None and user.is_authenticated:

            # 6.登陆用户redis
            #     6.1 连接redis
            redis_conn = get_redis_connection('cart')
            #     6.2 hash
            redis_conn.hdel('cart_%s'%user.id,sku_id)
            # set
            redis_conn.srem('cart_selected_%s'%user.id,sku_id)
            #     6.3 返回相应

            return Response(status=status.HTTP_204_NO_CONTENT)

        else:
            # 7.未登录用户cookie
            #     7.1 获取cart数据
            cookie_str = request.COOKIES.get('cart')
            #     7.2 判断cart数据
            if cookie_str is not None:
                cookie_cart = pickle.loads(base64.b64decode(cookie_str))
            else:
                cookie_cart = {}

            #     7.3 删除数据
            if sku_id in cookie_cart:
                del cookie_cart[sku_id]
            #     7.4 对字典进行加密处理
            cookie_encode = base64.b64encode(pickle.dumps(cookie_cart))
            #     7.5 返回相应
            response = Response(status=status.HTTP_204_NO_CONTENT)

            response.set_cookie('cart',cookie_encode.decode())

            return response